#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <ctype.h>

#include "od_engine.h"
#include "od_framework.h"
#include "param_msg.h"
#include "message.h"
#include "rpc_response.h"
#include "param_save.h"
#include "decoder_param.h"
#include "param_json.h"
#include "usecase_decoder.h"

/*default MQ TRANSFER NAME*/
#define DEF_MQ_TRANS_NAME  "decoder_mq_trans"
#define DFT_TRACE_FILE     "trace_decoder.ini"
#define DEMO_ARGC 7
#define TASK_HASH_TABLE_SIZE 1024


static int show_help()
{
    fprintf(stdout,
        "decoder.out:\n"
        "\n"
        "Usage: ./decoder.out [OPTION]\n"
        "\n"
        "Options:\n"
        "    -s,              src od_msg id\n"
        "    -f,              param file name include path\n"
        "    -p,              post transfer name\n"
        "    -h,              print this info \n"
        "\n"
        "Examples:\n"
        "    ./decoder.out -s 11 -f ./decoder.json -p decoder_mq_trans\n"
        "\n");

    return OD_OK;
}

typedef struct
{
    uint32_t src_id;
    char file_name[OD_MAX_PATH_LEN];
    char post_name[OD_MAX_PATH_LEN];
} decoder_startup_params;


static int deal_with_parameter(int argc, char *argv[], decoder_startup_params *startup_params)
{
    int i;

    strncpy(startup_params->post_name, DEF_MQ_TRANS_NAME, OD_MAX_PATH_LEN - 1);
    if(argc < DEMO_ARGC)
    {
        return OD_ERROR;
    }

    for(i = 1;i < argc;i++)
    {
        if('-' == argv[i][0])
        {
            if(0 == strcmp(argv[i], "-s") || 0 == strcmp(argv[i], "--src"))
            {
                if(i == argc-1)
                {
                    show_help();
                    return OD_ERROR;
                }
                i++;
                startup_params->src_id = atoi(argv[i]);
            }
            else if(0 == strcmp(argv[i], "-f") || 0 == strcmp(argv[i], "--file"))
            {
                if(i == argc-1)
                {
                    show_help();
                    return OD_ERROR;
                }
                i++;
                strncpy(startup_params->file_name, argv[i], OD_MAX_PATH_LEN - 1);
            }
            else if(0 == strcmp(argv[i], "-p") || 0 == strcmp(argv[i], "--post"))
            {
                if(i == argc-1)
                {
                    show_help();
                    return OD_ERROR;
                }
                i++;
                strncpy(startup_params->post_name, argv[i], OD_MAX_PATH_LEN - 1);
            }
            else
            {
                RPTERR("Wrong parameter:%c:%s", argv[i][0], argv[i]);
                show_help();
                return OD_ERROR;
            }
        }
        else
        {
            show_help();
            RPTERR("Wrong parameter: %s", argv[i]);
            return OD_ERROR;
        }
    }

    if(argc > DEMO_ARGC)
    {
        show_help();
        RPTERR("Wrong parameter nums : %d\n", argc - 1);
        return OD_ERROR;
    }

    return OD_OK;
}

param_save_list save_tab[] = {
    {NULL, 0, 0, NULL, NULL},
};

static void init_param_save_table(param_save_list s_list[], decoder_params_obj *decoder_handle)
{
    //只需初始化handle和filename，其他在param_save_create时初始化
    s_list[0].save_handle = decoder_handle->decoder_json_hdl;
    s_list[0].save_filename = decoder_handle->decoder_json_filename;
}

#define TAB_END {NULL, NULL, NULL}
rpc_response_tab_desc rpc_response_tab[] = {
    {"decoder.set", NULL, (void *)rpc_response_default_set},
    {"decoder.get", NULL, (void *)rpc_response_default_get},
    TAB_END
};

static void rpc_response_tab_init(rpc_response_tab_desc rpc_response_tab[], param_save_list save_tab[])
{
    rpc_response_tab[0].handle = rpc_response_tab[1].handle = &save_tab[0];
    return;
}

/*initialize the running environment*/
static void env_init()
{
   od_init();
   odin_trace_init(NULL, DFT_TRACE_FILE);
}

static void param_manage_create(decoder_startup_params *startup_params,
                                  decoder_params_obj * decoder_handle)
{
    param_save_static_params_t param_save_statics = glb_param_save_static_params_default;
    rpc_response_static_params_t rpc_response_statics = glb_rpc_response_static_params_default;

    /*初始化和启动参数保存线程*/
    param_save_statics.list_num = sizeof(save_tab)/sizeof(param_save_list);
    init_param_save_table(save_tab, decoder_handle);
    param_save_statics.s_list = save_tab;
    param_save_statics.save_func = NULL;
    decoder_handle->h_param_save = param_save_create(&param_save_statics, NULL);
    od_task_start(decoder_handle->h_param_save, 60);

    /*启动参数接收处理任务，可与其他任务交互*/
    rpc_response_tab_init(rpc_response_tab, save_tab);
    rpc_response_statics.msg_local_id = startup_params->src_id;
    rpc_response_statics.table = rpc_response_tab;
    strncpy(rpc_response_statics.post_name, startup_params->post_name, OD_MAX_OBJ_NAME - 1);
    decoder_handle->h_rpc_response = rpc_response_create(&rpc_response_statics, NULL);
    od_task_start(decoder_handle->h_rpc_response, 60);
}

static void param_manage_delete(decoder_params_obj * decoder_handle)
{
    od_task_stop(decoder_handle->h_param_save);
    od_task_delete(decoder_handle->h_param_save);

    od_task_stop(decoder_handle->h_rpc_response);
    od_task_delete(decoder_handle->h_rpc_response);
}

int main(int argc, char *argv[])
{
    int ret = OD_OK;
    od_framework_t * frameworks = NULL;
    decoder_params_obj * decoder_handle = NULL;
    decoder_startup_params startup_params;

    /*初始化环境*/
    env_init();
    memset(&startup_params, 0, sizeof(decoder_startup_params));
    if(deal_with_parameter(argc, argv, &startup_params) != 0)
    {
        show_help();
        return OD_ERROR;
    }

    /*创建framework*/
    frameworks = od_framework_create(sizeof(decoder_params_obj), TASK_HASH_TABLE_SIZE);
    decoder_handle = frameworks->param_table;
    if(NULL == decoder_handle)
    {
        RPTERR("decoder_handle alloc error");
        return OD_ERROR;
    }

    /*参数表初始化，读取json存储文件*/
    ret = decoder_params_init(frameworks, startup_params.file_name);
    if(0 != ret)
    {
        RPTERR("decoder_handle init error");
        return OD_ERROR;
    }

    /*启动需要启动的线程任务*/
    ret = decoder_start(frameworks);
    if(ret != OD_OK)
    {
        RPTERR("decoder_start error");
        return ret;
    }

    /*创建参数保存与设置任务*/
    param_manage_create(&startup_params, decoder_handle);
    od_msleep(1000);

    /*等待退出*/
    /*如果想要结束进程，设置exit变量，在其act响应函数中操作done，控制进程结束*/
    while (OD_OFF == decoder_handle->dec_params.done)
    {
        od_msleep(1000);
    }

    param_manage_delete(decoder_handle);
    /*参数保存任务退出*/

    /*退出*/
    decoder_stop(frameworks);
    RPTWRN("decoder_stop");
    decoder_params_destroy(frameworks);
    RPTWRN("param_destroy");

    od_framework_destroy(frameworks);
    RPTWRN("decoder exit");
    
    return OD_OK;
}


